/**
* 
* ====================================================================
*
* @author apov <apov@ymail.com>
*/ 
// Thread.h
//

#pragma once

#include "BaseDefine.h"

#ifdef WIN32
	#include <process.h>    /* _beginthread, _endthread */

	//#define DEF_THREAD_ENTRY_POINT		LPTHREAD_START_ROUTINE entry_point	
	#define DEF_THREAD_ENTRY_POINT		void (*entry_point)(void * data)
	#define DEF_THREAD_HANDLE			HANDLE	
	//#define DEF_THREAD_RETURN			DWORD WINAPI
	#define DEF_THREAD_RETURN			void
#else
	#include <unistd.h>
	#include <pthread.h>
	#define DEF_THREAD_ENTRY_POINT		void*(*entry_point)(void*)
	#define DEF_THREAD_HANDLE			pthread_t
	#define DEF_THREAD_RETURN			void*
#endif

#ifndef WIN32
#include <pthread.h>
#define DEF_LOCK	pthread_mutex_t
#else
#define DEF_LOCK	CRITICAL_SECTION
#endif

/**
* @class CLock
*  - 
*/
class DEFLIB_EXTERN_CLASS CLock{
public:
	void set_name( char* name );

	void Enter( char* caller = 0 );
	void Exit( char* caller = 0 );

	CLock();	
	virtual ~CLock();

protected:
	
private:
	friend class Notify;

	DEF_LOCK lock_;
	std::string name_;	
};

class DEFLIB_EXTERN_CLASS Notify{
public:	
	enum{
		DEF_SUCCESS,
		DEF_FAIL,		
		DEF_TIMEOUT,
		DEF_INFINITE,
	};

	bool initialize();
	bool call();
	int wait( int wait_time = DEF_INFINITE );

	Notify();
	virtual ~Notify();

protected:

private:
#ifdef WIN32
	HANDLE event_;
#else
	pthread_cond_t cond_;
#endif

	CLock lock_;
};

/**
* @class CBlanketLock
*  - 
*/
class BlanketLock{
public:
	BlanketLock(){
		lock_ = 0;
	}

	BlanketLock( CLock* lock, char* caller = 0 ){
		lock_ = lock;
		lock_->Enter( caller );
	}

	void setLock( CLock* lock, char* caller = 0 ){
		lock_ = lock;
		lock_->Enter( caller );
	}

	virtual ~BlanketLock(){
		if( lock_ )
			lock_->Exit();
	}

protected:
	
private:
	CLock* lock_;
};

/**
* @class CThread
*  - 
*/
class DEFLIB_EXTERN_CLASS CThread{
	enum{
		DEF_THREAD_EXIT_WAIT_TIME=		500,
	};

public:
	bool isActive();
	bool start(DEF_THREAD_ENTRY_POINT, void* arg);		
	bool stop();

	bool resume();
	bool suspend();

	unsigned long getID(){ return thread_id_; }

	//virtual DEF_THREAD_RETURN run(){ return 0; }
	virtual DEF_THREAD_RETURN run(){}
	DEF_THREAD_HANDLE getHandle(){ return thread_; }
	
	CThread();
	virtual ~CThread();

protected:
private:
	static DEF_THREAD_RETURN bridge(void* arg);

	unsigned long thread_id_;

	Notify event_;
	DEF_THREAD_HANDLE thread_;	
	volatile bool activate_;
};
